<?php
/**
* Applications
* Manage all requests of Viewers to be registered as Editors
* 
* @package Application
* @author Argem Gerald R. Flores <argemgrflores@gmail.com>
* @version 1.0
*/
class Application {
	/**
	* @var mixed Mysql connection
	*/
	var $mysqli = null;
	/**
	* @var array User credentials (id, email, type)
	*/
	var $user = null;
	/**
	* @var array Notifications
	*/
	var $notif = array();
	
	/**
	* Application constructor
	* Initializes Application variables for intended request
	* 
	* @param resource $mysqli Current mysql connection
	* @param resource $user User credentials (id, email, type)
	*/
	function __construct($mysqli, $user) {
		# require class Tool for extra functions
		require_once "class/tool.php";
		
		# assign mysql resource and user credentials
		$this->mysqli = $mysqli;
		$this->user = $user;
	} # function __construct
	
	/**
	* Search application
	* Searches for an application based on
	* query string, optional paramaters as constraints,
	* start and end line of result in a mysql resource
	* 
	* @access public
	* @param string $query Keyword/s to look for in the database
	* @param array $opts Contains constraints in search (category, order, author, etc.)
	* @param integer $start Beginning line of searched keyword in mysql resource
	* @param integer $limit End of returned mysql resource as a result of search
	* 
	* @return array Mixed result from mysql query and size of returned rows
	*/
	public function search($query, $opts, $start, $limit) {
		# Prepare query string
		$query = is_array($query) ? $query : str_replace(',', ' ', $query);
		# Prepare query string for size of rows returned
		$selSize = "SELECT FOUND_ROWS()";
		# Initialize cond string if any conditions will be added in search query
		$cond = "";
		
		# Set ordering of the results
		$opts['ob'] = isset($opts['ob']) ? $opts['ob'] : 'Lname, Fname';
		$opts['oa'] = isset($opts['oa']) ? $opts['oa'] : 'ASC';
		# Start and End of row search
		$start = isset($start) ? $start : '0';
		$limit = !empty($limit) ? $limit : '10';
		
		# Search for an application ID
		if($opts['c']=='id') {
			$sel = "SELECT * FROM Applications WHERE ID='{$query}' AND Remove='0' ORDER BY {$opts['ob']} {$opts['oa']}";
		}
		# Search for multiple ids
		else if($opts['c']=="multi-id") {
			$sel = "SELECT SQL_CALC_FOUND_ROWS * FROM Applications WHERE ID IN ('".implode("','", $query)."') AND Remove='0' ORDER BY {$opts['ob']} {$opts['oa']}";
		}
		elseif($opts['c']=="remove") {
			$sel = "SELECT SQL_CALC_FOUND_ROWS * FROM Applications WHERE Remove='1' ORDER BY {$opts['ob']} {$opts['oa']}";
		}
		# Search for anything else in applications
		else {
			# Partition query to array based on spaces contained
			$arrQuery = explode(" ", $query);
			# Conditional string
			$cond = " WHERE ";
			
			# Attach all elements in the query string to query
			foreach($arrQuery as $query) {
				# Trim out unnecessary characters from query string
				$query = Tool::trimout($query);
				
				# Query is contained in an Email, in Lastname or in Firstname
				$cond .= "Email LIKE '%{$query}%' OR ";
				$cond .= "Lname LIKE '%{$query}%' OR ";
				$cond .= "Fname LIKE '%{$query}%' OR ";
			}
			
			# Remove trailing OR in the query string
			$cond = substr($cond, 0, -4);
			
			# Removed items
			$cond .= (in_array($this->user['type'], array('ADMIN','PRIME')) and $opts['c']=='remove') ? " Remove='1' " : " Remove='0' ";
			
			# Final query string
			$sel = "
				SELECT SQL_CALC_FOUND_ROWS * FROM Applications {$cond} ORDER BY {$opts['ob']} {$opts['oa']} LIMIT {$start}, {$limit}
			";
		}
		
		# Perform mysql search
		$res = $this->mysqli->query($sel);
		# Select size of rows returned
		$size = $this->mysqli->query($selSize);
		$size = $size->fetch_row();
		
		# Return an array of results containing (1) mysql resource of rows and (2) number of rows
		return array($res, $size[0]);
	} # function search
	
	/**
	* Create application
	* Create an application request of a viewer
	* 
	* @access public
	* @param string $email Email of viewer
	* @param string $pword Password of viewer
	* @param string $lname Lastname of viewer
	* @param string $fname Firstname of viewer
	* @param string $mname Middlename of viewer
	* @param string $addrs Address of viewer
	* 
	* @return boolean True on successful filing of application, false on failure
	*/
	public function create($email, $pword, $lname, $fname, $mname, $addrs) {
		# Prepare values for mysql string query
		$id = Tool::generateID('appn');
		$email = Tool::mysqlEscStr($email);
		$pword = Tool::mysqlEscStr($this->hashsalt($pword));
		$lname = Tool::mysqlEscStr($lname);
		$fname = Tool::mysqlEscStr($fname);
		$mname = Tool::mysqlEscStr($mname);
		$addrs = Tool::mysqlEscStr($addrs);
		$date = date('Y-m-d H:i:s:ms');
		
		# Final mysql string query
		$ins = "
			INSERT INTO Applications VALUES (
				'$id', '$email', '$pword', '$lname', '$fname', '$mname', '$addrs', '$date', '0'
			)
		";
		
		# Do mysql query
		$res = $this->mysqli->query($ins);
		
		# An error occurred
		if(!$res) {
			return false;
		}
		
		# Approve application right away
		if(($search = $this->search($id, array('c'=>'id'), 0, 1)) and $this->approve($search[0]->fetch_object())) {
			return true;
		}
		
		# Inserted application successfully
		return true;
	} # function create
	
	/**
	* Reject application
	* Removes an entry from the list of pending applications
	* 
	* @access public
	* @param string $id Application ID
	* 
	* @return boolean True on successful removal of application, false on failure
	*/
	public function reject($id) {
		# Delete an application based on passed id
		$del = "UPDATE Applications SET Remove='1' WHERE ID='{$id}'";
		
		# Do delete query on mysql
		$res = $this->mysqli->query($del);
		
		# An error occurred
		if(!$res) {
			return false;
		}
		
		# Rejected application successfully
		return true;
	} # function reject
	
	/**
	* Approve application
	* Create an account based on application details
	* 
	* @access public
	* @param object $appn Application details
	* 
	* @return boolean True on successful removal of application, false on failure
	*/
	public function approve($appn) {
		# Instantiate a new Account for creating request
		$acct = new Account($this->mysqli, $this->user);
		
		# Create an account
		$id = $acct->create('CLIENT', $appn->Email, $appn->Pword, $appn->Lname, $appn->Fname, $appn->Mname, $appn->Addrs);
		
		# An error occurred in creating account 
		if(!$id) {
			$this->notif[] = "<li>Cannot approve application of <b>{$appn->Lname}, {$appn->Fname} ({$appn->Email})</b></li>";
		}
		
		# Created an account successfully but removing of application unsuccessful
		if($id and !$this->delete($appn->ID)) {
			$this->notif[] = "<li>Cannot delete application of <b>{$appn->Lname}, {$appn->Fname} ({$appn->Email})</b></li>";
		}
		
		# Notification is not empty meaning there could be an error found
		if(!empty($this->notif)) {
			# Pass notification as a json note
			setcookie('note', json_encode($this->notif));
			return false;
		}
		
		# return ID of newly created Account
		return $id;
	} # function approve
	
	/**
	* Hash password
	* Encrypt user password using sha512 hash algorithm
	* 
	* @access public
	* @param string $pword Password of an account to be created or verified
	* 
	* @return string Encrypted string of the password
	*/
	public function hashsalt($pword) {
		return hash('sha512', $pword);
	} # function hashsalt
	
	/**
	* Display all applications
	* Retrieve all contents of applications on a page
	* 
	* @access public
	* @param array $queries IDs of applications
	*/
	public function displayAll($queries, $opts) { ?>
		<output> <?php
			if($results = $this->search($queries, $opts, 0, 10)) {
				while($result = $results[0]->fetch_object()) {
					$this->displayContent($result, false);
				}
			} ?>
		</output> <?php
	}
	
	/**
	* Guess application
	* Provides a list of applications (guess) on user input
	* Makes selection of application and id faster
	* 
	* @access public
	* @param string $query Application's name or email to be searched for
	* 
	* @return mixed|false Mixed if query is found, false if not
	*/
	public function guess($query) {
		# Search for applications matching the query string and constrains passed
		$appns = $this->search($query, $_REQUEST, 0, 10);
		
		# Application is not found
		if(!$appns or empty($appns[1])) {
			return false;
		}
		
		while($appn = $appns[0]->fetch_object()) { ?>
			<div class="guess appn" data-id="<?php echo $appn->ID ?>" data-id="<?php echo $appn->ID ?>"
				data-value="<?php echo $appn->Lname.", ".$appn->Fname.", ".$appn->Mname ?>" tabindex="0">
				<?php echo $appn->Lname.", ".$appn->Fname.", ".substr($appn->Mname, 0, 1)."." ?>
			</div> <?php
		}
		
		if($_REQUEST['s']=='true') { ?>
			<div class="guess-header appn query">
				<a href="main.php?appn=view&q=<?php echo urlencode($query) ?>" target="_blank" title="<?php echo $query ?>"><?php echo Tool::truncate($query, 30) ?></a>
				<span class="right bold none" title="<?php echo ($found = $appns[0]->num_rows.' of '.$appns[1]).' items found' ?>"><?php echo $found ?></span>
			</div> <?php
		}
	} # function guess
	
	/**
	* Display main application stage
	* List all applications in the main page
	* 
	* @access public
	* @param mixed $appns List of applications from returned search results
	* @param integer $size Size of rows from returned search results
	* @param string $query Query string that was searched for
	* @param array $opts Optional parameters
	* @param integer $start Starting row in mysql returned results
	*/
	public function displayMain($appns, $size, $query, $opts, $start) {
		# Check if one account is to be displayed
		$view = $appns->num_rows==1;
		# Get page number
		$page = ceil(($start+1)/10);
		# Prepare GET variables
		$optstr = Tool::optstrify($opts); ?>
		
		<div id="side"> <?php
			# Show Back and Next buttons for navigation ?>
			<div id="navis"> <?php
				# Links to previous ten items ?>
				<a href="main.php?<?php echo $optstr.(empty($query) ? '' : '&q='.$query).(empty($start) ? '&s=0' : '&s='.(intval($start)-10)) ?>"
					class="navi ui ui-button prev <?php if(empty($start)) echo 'disabled' ?>" tabindex="-1" title="Previous 10 items"></a> <?php
				# Links to next ten items ?>
				<a href="main.php?<?php echo $optstr.(empty($start) ? '&s=10' : '&s='.(intval($start)+10)) ?>"
					class="navi ui ui-button next <?php if(($appns->num_rows<10) or ($appns->num_rows*$page)>=$size) { echo 'disabled'; } ?>" tabindex="-1" title="Next 10 items"></a>
			</div> <?php
			
			# Knobs to stage an application ?>
			<div id="knobs"> <?php $i = 1;
				while($appn = $appns->fetch_object()) {
					# Contains data query (Email), id (Account ID), tool (tooltip help)
					$name = Tool::truncate($trname = "{$appn->Lname}, {$appn->Fname}, ".substr($appn->Mname, 0, 1).'.', 80); ?>
					<div id="knob<?php echo $appn->ID ?>" class="knob appn <?php if($view) echo "lock" ?>" data-kword="<?php echo $appn->Email ?>"
						data-id="<?php echo $appn->ID ?>" data-tool="{'head':'<b class=\'cool\'><?php echo $name ?></b>','x':'l'}">
						<?php echo $i++; ?>
					</div> <?php
				} ?>
			</div>
		</div> <?php
		
		# Labels stage items (header) ?>
		<div id="hnotif" class="escape"> <?php
			# Shows metadata of all searched items ?>
			<span id="query" class="escape iblock" data-tool="{'head':'<?php echo ($all = empty($query)) ? "All applications" : $trname ?>','x':'l'}"
				<?php if(!($nctrl = empty($_COOKIE['ctrl']['search']))) { echo 'style="width:400px"'; } ?>>
				<?php echo ($all ? "All applications" : ($view ? $name : $query)) ?>
			</span>
			
			<span>
				<span id="search-ctrls" <?php if($nctrl) { echo 'class="none"'; } ?>> <?php
					# No. of returned results
					echo '<span id="numresults">Showing '.($appns->num_rows).' of <b>'.$size.'</b> result(s)</span> on page ';
					
					# Many microorganisms are to be viewed
					$ob = isset($_REQUEST['ob']); $of = true;
					unset($opts['ob']); unset($opts['oa']);
					$optstr = Tool::optstrify($opts);
					
					# Prepare filter options and page selector ?>
					<select id="main-page" class="page navi" data-tool="{'head':'Page'}"> <?php
						for($i=0, $x=$size/10; $i<$x; $i++)	echo "<option ".((isset($opts['s']) and $opts['s']==($i*10)) ? 'selected="selected"' : '').'value="main.php?'.$optstr.(empty($query) ? '' : '&q='.$query).'&s='.($i*10).'">'.($i+1).'</option>';?>
					</select> sorted by <?php
					
					# Prepare filter options ?>
					# Prepare filter options ?>
					<select class="navi" data-tool="{'head':'Page'}">
						<option value="main.php?<?php echo $optstr ?>&ob=lname&oa=asc" <?php if($ob and $_REQUEST['ob']=='lname') { echo 'selected="selected"'; $of = false; } ?>>Name</option>
						<option value="main.php?<?php echo $optstr ?>&ob=email&oa=asc" <?php if($ob and $_REQUEST['ob']=='email') { echo 'selected="selected"'; $of = false; } ?>>Email</option>
						<option value="main.php?<?php echo $optstr ?>&ob=crton&oa=desc" <?php if($ob and $_REQUEST['ob']=='crton') { echo 'selected="selected"'; $of = false; } ?>>Date filed</option>
						<option value="main.php?<?php echo $optstr ?>&ob=id&oa=asc" <?php if($ob and $_REQUEST['ob']=='id') { echo 'selected="selected"'; $of = false; } ?>>ID</option>
					</select>
				</span>
				<span <?php if(!$nctrl) { echo 'class="none"'; } ?>><?php echo "$appns->num_rows of <b>$size</b> result(s) on page <b>$page</b>";  ?></span> <button type="button" class="navi-details <?php echo (!$nctrl ? 'selected' : '') ?>" data-tool="{'head':'Search controls'}"></button>
			</span>
		</div> <?php
		
		# Contains all application headers ?>
		<div id="stage"> <?php
			# Reset pointer to first row in mysql result
			$appns->data_seek(0);
			
			# List all applications on its own entry page
			while($appn = $appns->fetch_object()) {
				# Show first the heading of each application
				$this->displayHeading($appn, $view);
			} ?>
		</div> <?php
	} # function displayMain
	
	/**
	* Display an application heading
	* Displays a heading for each application in the results
	* which contains the application's full name and email
	* 
	* @access public
	* @param mixed $appn Contains all details of the application
	* @param boolean $cont Checks if content is to be displayed too
	*/
	public function displayHeading($appn, $cont) {
		# List an application first as an area with a header that can be selected/clicked by the user in the stage
		# Data included: head (name of the application holder), id (application id)
		?> <div id="area<?php echo $appn->ID ?>" data-id="<?php echo $appn->ID ?>" class="stage area appn"
				data-head="<?php echo $name = "{$appn->Lname}, {$appn->Fname}, ".substr($appn->Mname, 0, 1).'.' ?>">
			<div class="div-header appn <?php echo $cont ? "active lock" : "heading" ?>" data-id="<?php echo $appn->ID ?>" data-content="appn">
				<a href="main.php?appn=view&id=<?php echo $appn->ID ?>" class="name"><?php echo $name ?></a>
				<div class="email right"><?php echo $appn->Email ?></div>
			</div> <?php
			
			# Show application's contents if necessary
			if($cont) {
				$this->displayContent($appn, $cont);
			} ?>
		</div> <?php
	} # function displayHeading
	
	/**
	* Display application contents
	* Displays the contents of an application, from its name to its address
	* 
	* @access public
	* @param mixed $appn Contains all details of the application
	* @param boolean $cont Checks if only one application is found in results
	*/
	public function displayContent($appn, $cont) {
		?> <div class="div-content">
			<form id="form-appn<?php echo $appn->ID ?>" data-id="<?php echo $appn->ID ?>" name="form-appn[]" class="appn" novalidate="novalidate">
			<div class="div-upper">
				<div class="div-body alright"> <?php
					# Displays all the necessary details of the application ?>
					<label>Email:</label> <input name="email" type="email" value="<?php echo $appn->Email ?>" readonly="readonly"/><br/>
					<label>Password:</label> <input name="pword" type="text" placeholder="Hidden" readonly="readonly"/><br/>
					<label>Last name:</label> <input name="lname" type="text" value="<?php echo $appn->Lname ?>" readonly="readonly"/><br/>
					<label>First name:</label> <input name="fname" type="text" value="<?php echo $appn->Fname ?>" readonly="readonly"/><br/>
					<label>Middle name:</label> <input name="mname" type="text" value="<?php echo $appn->Mname ?>" readonly="readonly"/><br/>
					<label>Address:</label> <input name="addrs" type="text" value="<?php echo $appn->Addrs ?>" readonly="readonly"/>
				</div> <div class="div-head"></div>
			</div>
			
			<div class="div-dial"> <?php
				if($appn->Remove!='1') { ?>
					<button type="button" class="reject-appn" data-id="<?php echo $appn->ID ?>">Reject</button>
					<button type="submit">Approve</button> <?php
				}
				
				# Show close if not a solo application
				if(!$cont) { ?>
					<button type="button" class="close-content reset">Close</button> <?php
				} ?>
			</div>
			</form>
		</div> <?php
	} # function displayContent
} # class Application
?>
